package com.e3.toolkit;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JToolBar;

import com.e3.toolkit.TableMeta.ColumnMeta;

public class EntityGMain extends JFrame {

	private static final long serialVersionUID = 1430648923318022394L;
	
	private JPanel centerPanel = new JPanel(new BorderLayout());


	private JPanel messagePanel = new JPanel(new BorderLayout());
	private JProgressBar processBar = new JProgressBar();
	
	private JToolBar toolBar = new JToolBar();
	private ConnectAction conAction = new ConnectAction(this);
	private RefreshAction refreshAction = new RefreshAction(this);
	private TransferAction transferAction = new TransferAction(this);
	
	private JPanel tableListPanel = new JPanel(new GridLayout(1,2));
	private JScrollPane lScrollPane = new JScrollPane();
	private JList lTablesList = new JList();
	
	private ConnectDialog connectDialog = null;
	private ClassInfoDialog classInfoDialog = null;
		
	private Connection conn;
	
	public EntityGMain(){
		init();
	}
	private void init(){
		this.setTitle("Tools for Entity&Model&Field");
		
		tableListPanel.add(lScrollPane);

		lScrollPane.getViewport().add(lTablesList);
		
		Box box1 = new Box(BoxLayout.Y_AXIS);
		box1.add(processBar);
		messagePanel.add(box1,BorderLayout.CENTER);
		
		centerPanel.add(tableListPanel,BorderLayout.CENTER);
		centerPanel.add(messagePanel,BorderLayout.SOUTH);
		
		toolBar.add(conAction);
		toolBar.add(refreshAction);
		toolBar.add(transferAction);
		//toolBar.add(commitAction);
		
		this.add(toolBar,BorderLayout.NORTH);
		this.getContentPane().add(centerPanel);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setPreferredSize(new Dimension(800,600));
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		this.setLocation((int)screenSize.getWidth()/2-400, (int)screenSize.getHeight()/2-300);
		
		this.addWindowListener(new WindowAdapter(){

			@Override
			public void windowClosed(WindowEvent e) {
				if(conn!=null){
					try {
						conn.close();
					} catch (Exception e2) {
						e2.printStackTrace();
					}
				}
			}
			
		});
		
	}

	private class TransferAction extends AbstractAction{
		private static final long serialVersionUID = -3681374552218717937L;
		private final JFrame frame ;
		
		public TransferAction(JFrame frame) {
			super("Generate");
			this.frame = frame;
		}

		public void actionPerformed(ActionEvent e) {
			//final DefaultListModel lListModel = (DefaultListModel)lTablesList.getModel();
			Object[] values = lTablesList.getSelectedValues();
			if(values==null||values.length==0){
				JOptionPane.showMessageDialog(frame, "请选择表");
				return;
			}
			
			TableMeta meta = (TableMeta)values[0];
			if(classInfoDialog==null){
				classInfoDialog = new ClassInfoDialog(frame);
				classInfoDialog.setLocationRelativeTo(toolBar.getComponent(2));
				classInfoDialog.pack();
				classInfoDialog.setModal(true);
			}
			classInfoDialog.showDialog(meta);
		}
		
	}

	private class RefreshAction extends AbstractAction{

		private static final long serialVersionUID = -5066459992030845911L;

		private final JFrame frame ;
		
		public RefreshAction(JFrame frame) {
			super("Refresh");
			this.frame = frame;
			
		}

		public void actionPerformed(ActionEvent e) {
			readDBMeta();
		}
		
	}
	private class ConnectAction extends AbstractAction{

		private static final long serialVersionUID = -5066459992030845911L;

		private final JFrame frame ;
		
		public ConnectAction(JFrame frame) {
			super("Connect...");
			this.frame = frame;
			
		}

		public void actionPerformed(ActionEvent e) {
			if(connectDialog == null){
				connectDialog = new ConnectDialog(frame);
				connectDialog.setLocationRelativeTo(toolBar.getComponent(2));
				connectDialog.pack();
			}
			connectDialog.setVisible(true);
		}
		
	}

	private class ClassInfoDialog extends JDialog{
		private static final long serialVersionUID = 1L;

		private JPanel centerPanel = new JPanel(null);
		private JPanel buttonPanel = new JPanel();
		
		private JButton okButton = new JButton("Accept");
		private JButton cancelButton = new JButton("Cancel");
		
		private JTextField pathField = new JTextField();
		private JTextField packageNameField = new JTextField();
		private JTextField classNameField = new JTextField();
		
		private TableMeta meta;
		public ClassInfoDialog(Frame owner) {
			super(owner);
			this.init();
		}
		
		private void init(){
			centerPanel.setPreferredSize(new Dimension(300,150));
			
			okButton.setPreferredSize(new Dimension(100,27));
			cancelButton.setPreferredSize(new Dimension(100,27));
			
			
			createField("包名", 0, packageNameField);
			
			createField("类名", 1, classNameField);
			
			
			createField("输出到", 2,pathField);
					
			buttonPanel.add(okButton);
			buttonPanel.add(cancelButton);
			
			this.getContentPane().add(centerPanel,BorderLayout.CENTER);
			this.getContentPane().add(buttonPanel,BorderLayout.SOUTH);
			this.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
			this.setPreferredSize(new Dimension(400,300));
			this.setResizable(false);
			this.setModal(true);
			
			cancelButton.addActionListener(new ActionListener(){

				public void actionPerformed(ActionEvent e) {
					onCancelButton();
				}
			});
			okButton.addActionListener(new ActionListener(){

				public void actionPerformed(ActionEvent e) {
					onOkButton();
				}
			});
			
		}
		public void showDialog(TableMeta meta){
			this.meta = meta;
			packageNameField.setText("com.e3.");
			classNameField.setText(meta.getClassName());
			String path = new File(".").getAbsolutePath();
			//path = path.substring(0,path.indexOf("toolkit"));
			pathField.setText(path+"\\src");
			this.setVisible(true);
		}
		private void onCancelButton() {
			this.setVisible(false);
		}
		private void onOkButton() {
			String pkName = packageNameField.getText();
			String czName = classNameField.getText();
			String pName = pathField.getText();
			pkName = pkName==null?"":pkName.trim();
			czName = czName==null?"":czName.trim();
			pName = pName == null?"":pName.trim();
			if(pkName.length()==0||czName.length()==0||pkName.endsWith(".")){
				JOptionPane.showMessageDialog(this, "请输入包名和类名");
				return;
			}
			
			TransferUtils.transfer(pName, pkName, czName, meta);
			this.setVisible(false);
		}
		private void createField(String name,int row, JComponent field){
			JLabel label = new JLabel(name);
			label.setHorizontalTextPosition(JLabel.RIGHT);
			//label.setPreferredSize(new Dimension(40,27));
			label.setBounds(20,30*(row + 1)+10,100,27);
			//field.setPreferredSize(new Dimension(120,27));
			field.setBounds(140, 30*(row + 1)+10, 220, 27);
			
			centerPanel.add(label);
			centerPanel.add(field);
		}
	}
	
	private class ConnectDialog extends JDialog{

		private static final long serialVersionUID = 3527154506549381776L;
		
		private JPanel centerPanel = new JPanel(null);
		private JPanel buttonPanel = new JPanel();
		
		private JButton okButton = new JButton("Accept");
		private JButton cancelButton = new JButton("Cancel");
		
		private JTextField userNameField = new JTextField();
		private JPasswordField passwordField = new JPasswordField();
		private JTextField conntectionUrlField = new JTextField();
		private JTextField driverName = new JTextField();
		private JTextField driverPath = new JTextField();
		
		//private DefaultComboBoxModel dbTypeListModel = new DefaultComboBoxModel();
		//private JComboBox dbTypeList = new JComboBox(dbTypeListModel);
		
		public ConnectDialog(Frame owner) {
			super(owner);
			this.init();
		}

		private void init(){
			this.setTitle("Connect To Database");
			
			centerPanel.setPreferredSize(new Dimension(300,150));
			
			okButton.setPreferredSize(new Dimension(100,27));
			cancelButton.setPreferredSize(new Dimension(100,27));
						
			userNameField.setText("root");
			createField("user name",0,userNameField);
			passwordField.setText("root");
			createField("password",1,passwordField);
			
			conntectionUrlField.setText("jdbc:mysql://localhost:3306/erp3?useUnicode=true&characterEncoding=utf8");
			createField("connection url",2,conntectionUrlField);
			
			driverName.setText("com.mysql.jdbc.Driver");
			createField("driver name",3,driverName);
			
			buttonPanel.add(okButton);
			buttonPanel.add(cancelButton);
			
			cancelButton.addActionListener(new ActionListener(){

				public void actionPerformed(ActionEvent e) {
					onCancelButton();
				}
				
			});
			okButton.addActionListener(new ActionListener(){

				public void actionPerformed(ActionEvent e) {
					onOkButton();
				}
				
			});
						
			this.getContentPane().add(centerPanel,BorderLayout.CENTER);
			this.getContentPane().add(buttonPanel,BorderLayout.SOUTH);
			this.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
			this.setPreferredSize(new Dimension(400,300));
			this.setResizable(false);
			this.setModal(true);
		}

				
		private void createField(String name,int row, JComponent field){
			JLabel label = new JLabel(name);
			label.setHorizontalTextPosition(JLabel.RIGHT);
			//label.setPreferredSize(new Dimension(40,27));
			label.setBounds(20,30*(row + 1)+10,100,27);
			//field.setPreferredSize(new Dimension(120,27));
			field.setBounds(140, 30*(row + 1)+10, 220, 27);
			
			centerPanel.add(label);
			centerPanel.add(field);
		}
		
		private void onCancelButton(){
			this.setVisible(false);
			
		}
		
		private void onOkButton(){
			String uName = this.userNameField.getText();
			String passw = String.valueOf(this.passwordField.getPassword());
			String conUrl = this.conntectionUrlField.getText();
			String drPath = this.driverPath.getText();
			String drName = this.driverName.getText();
			
			uName = uName.trim();
			conUrl = conUrl.trim();
			drPath = drPath.trim();
			drName = drName.trim();

			try{
				Class.forName(drName);
				conn = DriverManager.getConnection(conUrl, uName, passw);
			
				readDBMeta();
				
				this.setVisible(false);
			}
			catch(Exception e){
				e.printStackTrace();
				if(conn!=null){
					try {
						conn.close();
					} catch (SQLException ex) {
						ex.printStackTrace();
					}
				}
			}
			
		}
		
	}

	private void readDBMeta(){
		DefaultListModel lListModel = new DefaultListModel();
		Map<String,TableMeta> metaMaps = new HashMap<String,TableMeta>();
		ResultSet rs = null;
		ResultSet rs1 = null;
		try {
			rs = conn.getMetaData().getColumns("erp3", "%", "t_%",null);
			while(rs.next()){
				String tableName = rs.getString("TABLE_NAME");
				if("t_superfield".equalsIgnoreCase(tableName)
						||"t_superbill".equalsIgnoreCase(tableName)){
					continue;
				}
				TableMeta tableMeta = metaMaps.get(tableName);
				if(tableMeta==null){
					tableMeta = new TableMeta(tableName);
					metaMaps.put(tableName, tableMeta);
				}
				String colName = rs.getString("COLUMN_NAME");
				if("bill_type".equalsIgnoreCase(colName)){
					tableMeta.setBillEntity(true);
				}
				else if("corp_id".equalsIgnoreCase(colName)){
					tableMeta.setOCEntity(true);
				}
				if("id".equalsIgnoreCase(colName)
					||"create_user_id".equalsIgnoreCase(colName)
					||"create_time".equalsIgnoreCase(colName)
					||"modify_user_id".equalsIgnoreCase(colName)
					||"modify_time".equalsIgnoreCase(colName)
					||"status".equalsIgnoreCase(colName)
					||"approver_id".equalsIgnoreCase(colName)
					||"approve_time".equalsIgnoreCase(colName)
					||"bill_type".equalsIgnoreCase(colName)
					||"parent_bill_type".equalsIgnoreCase(colName)
					||"parent_bill_id".equalsIgnoreCase(colName)
					||"parent_bill_rowid".equalsIgnoreCase(colName)
					||"source_bill_type".equalsIgnoreCase(colName)
					||"source_bill_id".equalsIgnoreCase(colName)
					||"source_bill_rowid".equalsIgnoreCase(colName)
					||"delete_flag".equalsIgnoreCase(colName)
					||"corp_id".equalsIgnoreCase(colName)
					){
					continue;
				}
				ColumnMeta cm = tableMeta.createColMeta();
				cm.setColName(colName);
				cm.setDataType(rs.getInt("DATA_TYPE"));
				cm.setDataTypeName(rs.getString("TYPE_NAME"));
				cm.setLength(rs.getInt("COLUMN_SIZE"));
				cm.setDigits(rs.getInt("DECIMAL_DIGITS"));
				cm.setNullable(rs.getBoolean("IS_NULLABLE"));
			}
			Iterator<String> it = metaMaps.keySet().iterator();
			while(it.hasNext()){
				String tableName = it.next();
				TableMeta tMeta = metaMaps.get(tableName);
				rs1 = conn.getMetaData().getPrimaryKeys("erp3", "%", tableName);
				rs1.next();
				if(rs1.getRow()==0){
					continue;
				}
				String pkName = rs1.getString("COLUMN_NAME");
				tMeta.setPrimaryKey(pkName);
				lListModel.addElement(tMeta);
			}
			
			lTablesList.setModel(lListModel);
		} catch (Exception e) {
			e.printStackTrace();
		}
		finally{
			if(rs!=null){
				try {
					rs.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(rs1!=null){
				try {
					rs1.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void main(String[] args){
		EntityGMain frame = new EntityGMain();
		frame.pack();
		frame.setVisible(true);
	}
}
